package com.learn.english.service;

import com.alibaba.fastjson2.JSON;
import com.learn.english.enums.TimeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author TISNIW
 * @version 1.0
 * @date 2025/5/2 15:10
 * @desc
 */


@Component
public class RedisService {

    private final RedisTemplate<String, Object> redisTemplate;

    @Autowired
    public RedisService(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    // --------------------- Key 操作 ---------------------

    public Boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }

    public boolean expire(String key, long timeout, TimeUnit unit) {
        return Boolean.TRUE.equals(redisTemplate.expire(key, timeout, unit));
    }

    public Long getExpire(String key, TimeUnit unit) {
        return redisTemplate.getExpire(key, unit);
    }

    public boolean deleteObject(String key) {
        return Boolean.TRUE.equals(redisTemplate.delete(key));
    }

    // --------------------- String 操作 ---------------------

    public <T> void setCacheObject(String key, T value) {
        redisTemplate.opsForValue().set(key, value);
    }

    public <T> void setCacheObject(String key, T value, TimeEnum time) {
        redisTemplate.opsForValue().set(key, value, time.getTimeout(), time.getUnit());
    }

    public <T> T getCacheObject(String key, Class<T> clazz) {
        Object value = redisTemplate.opsForValue().get(key);
        if (value == null) return null;
        if (clazz.isAssignableFrom(value.getClass())) {
            return clazz.cast(value);
        }
        return JSON.parseObject(JSON.toJSONString(value), clazz);
    }

    public <T> List<T> multiGet(List<String> keys, Class<T> clazz) {
        List<Object> values = redisTemplate.opsForValue().multiGet(keys);
        if (CollectionUtils.isEmpty(values)) return null;
        List<T> result = new ArrayList<>();
        for (Object value : values) {
            result.add(JSON.parseObject(JSON.toJSONString(value), clazz));
        }
        return result;
    }

    public void multiSet(Map<String, Object> map) {
        redisTemplate.opsForValue().multiSet(map);
    }

    public Long increment(String key) {
        return redisTemplate.opsForValue().increment(key);
    }

    // --------------------- List 操作 ---------------------

    public Long getListSize(String key) {
        return redisTemplate.opsForList().size(key);
    }

    public <T> List<T> getCacheListByRange(String key, long start, long end, Class<T> clazz) {
        List<?> list = redisTemplate.opsForList().range(key, start, end);
        if (CollectionUtils.isEmpty(list)) return null;
        return JSON.parseArray(JSON.toJSONString(list), clazz);
    }

    public <T> Long rightPushAll(String key, Collection<T> list) {
        return redisTemplate.opsForList().rightPushAll(key, list);
    }

    public <T> Long leftPushForList(String key, T value) {
        return redisTemplate.opsForList().leftPush(key, value);
    }

    public <T> Long removeForList(String key, T value) {
        return redisTemplate.opsForList().remove(key, 1L, value);
    }

    public <T> Long indexOfForList(String key, T value) {
        return redisTemplate.opsForList().indexOf(key, value);
    }

    public <T> T indexForList(String key, long index, Class<T> clazz) {
        Object value = redisTemplate.opsForList().index(key, index);
        return value == null ? null : JSON.parseObject(JSON.toJSONString(value), clazz);
    }

    // --------------------- Hash 操作 ---------------------

    public <T> T getCacheMapValue(String key, String hKey, Class<T> clazz) {
        Object value = redisTemplate.opsForHash().get(key, hKey);
        return value == null ? null : JSON.parseObject(JSON.toJSONString(value), clazz);
    }
    public <T> List<T> getMultiCacheMapValue(String key, Collection<String> hKeys, Class<T> clazz) {
        RedisSerializer<String> serializer = RedisSerializer.string();
        List<byte[]> byteKeys = new ArrayList<>();
        for (String hKey : hKeys) {
            byteKeys.add(serializer.serialize(hKey));
        }

        List<?> values = redisTemplate.opsForHash().multiGet(key, Collections.singleton(byteKeys));
        if (CollectionUtils.isEmpty(values)) return null;

        List<T> result = new ArrayList<>();
        for (Object value : values) {
            result.add(JSON.parseObject(JSON.toJSONString(value), clazz));
        }
        return result;
    }

    public <T> void setCacheMapValue(String key, String hKey, T value) {
        redisTemplate.opsForHash().put(key, hKey, value);
    }

    public <K, T> void setCacheMap(String key, Map<K, T> dataMap) {
        if (dataMap != null) {
            redisTemplate.opsForHash().putAll(key, dataMap);
        }
    }

    public Long deleteCacheMapValue(String key, String hKey) {
        return redisTemplate.opsForHash().delete(key, hKey);
    }

    public Long incrementHashValue(String key, String hKey, long delta) {
        return redisTemplate.opsForHash().increment(key, hKey, delta);
    }
}